package com.dd.cloud.user.service.drugs.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dd.cloud.common.constants.DrugsConstants;
import com.dd.cloud.common.constants.PresConstants;
import com.dd.cloud.user.entity.drugs.DrugsWarehousing;
import com.dd.cloud.user.entity.pres.DrugsModel;
import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.user.mapper.drugs.DrugsWarehousingMapper;
import com.dd.cloud.user.req.drugs.AddDrugsWarehousingReq;
import com.dd.cloud.user.req.drugs.DrugsQtyPageReq;
import com.dd.cloud.user.req.drugs.DrugsWarePageReq;
import com.dd.cloud.user.req.drugs.ExcelAddDrugsWarehousingReq;
import com.dd.cloud.user.res.drugs.DrugsQtyPageRes;
import com.dd.cloud.user.res.drugs.DrugsQtyRes;
import com.dd.cloud.user.res.drugs.DrugsWarePageRes;
import com.dd.cloud.user.service.drugs.IDrugsWarehousingService;
import com.dd.cloud.user.service.phar.IPharmacyService;
import com.dd.cloud.user.service.pres.IDrugsModelService;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.common.enums.ZkExceptionEnum;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.utils.ExtUtils;
import com.dd.cloud.common.utils.ValidatorUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 药品入库记录表 服务实现类
 * </p>
 *
 * @author czg
 * @since 2023-04-18
 */
@Service
public class DrugsWarehousingServiceImpl extends ServiceImpl<DrugsWarehousingMapper, DrugsWarehousing> implements IDrugsWarehousingService {

    @Autowired
    private IDrugsModelService drugsModelService;
    @Autowired
    private IPharmacyService pharmacyService;

    /**
     * @return void
     * @description 添加入库记录
     * @description 添加入库记录
     * @description 添加入库记录
     * @author czg
     * @date 2023/4/19 10:29
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addDrugsWarehousing(AddDrugsWarehousingReq req) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo(LoginInfo.UserType.PHAR).get();
        QueryWrapper<DrugsWarehousing> qw = new QueryWrapper<>();
        qw.lambda().eq(DrugsWarehousing::getReceiptNo, req.getReceiptNo())
                .eq(DrugsWarehousing::getStatus, DrugsConstants.WareStatus.NOMAL);
        DrugsWarehousing one = getOne(qw);
        if (one != null) {
            throw new ZekeException("单据号已存在");
        }
        QueryWrapper<DrugsModel> qs = new QueryWrapper<>();
        qs.lambda().eq(DrugsModel::getDrugnum, req.getDrugnum())
                .eq(DrugsModel::getPharId, loginInfo.getPharId())
                .ne(DrugsModel::getStatus, PresConstants.ModelDrugsStatus.DEL);
        DrugsModel model = drugsModelService.getOne(qs);
        if (model == null) {
            throw new ZekeException("药品编码不存在");
        }
        DrugsWarehousing drugsWarehousing = new DrugsWarehousing();
        BeanUtils.copyProperties(req, drugsWarehousing);
        drugsWarehousing.setCreateDate(LocalDateTime.now());
        drugsWarehousing.setStatus(DrugsConstants.WareStatus.NOMAL);
        drugsWarehousing.setOperId(loginInfo.getId());
        drugsWarehousing.setPharId(loginInfo.getPharId());
        drugsWarehousing.setCostPrice(req.getOriginalPrice());
        drugsWarehousing.setPharId(loginInfo.getPharId());
        boolean save = save(drugsWarehousing);
        if (!save) {
            throw new ZekeException(ZkExceptionEnum.ADD_ERROR);
        }
        model.setQty(model.getQty().add(drugsWarehousing.getWareQty()));
        save = drugsModelService.updateById(model);
        if (!save) {
            throw new ZekeException(ZkExceptionEnum.UPDATE_ERROR);
        }
    }

    /**
     * @param file:
     * @return Map<String, Integer>
     * @description 批量导入药品入库记录
     * @author czg
     * @date 2023/4/19 11:49
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, String> importExcelDrugsWare(MultipartFile file) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        List<ExcelAddDrugsWarehousingReq> list;
        try {
            if (file == null) {
                throw new ZekeException("请上传文件");
            }
            list = ExtUtils.importExcel(file, 1, 1, ExcelAddDrugsWarehousingReq.class);
        } catch (IOException e) {
            e.printStackTrace();
            throw new ZekeException("解析Excel失败");
        }
        if (list == null || list.isEmpty()) {
            throw new ZekeException("上传数据为空");
        }
        List<String> failModel = new ArrayList<>();
//        int i = 2;
        for (ExcelAddDrugsWarehousingReq model : list) {
//            i++;
            String verifyStr = ValidatorUtils.verifyStr(model, ExcelAddDrugsWarehousingReq.class);
            if (!StringUtils.isBlank(verifyStr)) {
                failModel.add(model.getHerbName());
                continue;
            }
            QueryWrapper<DrugsWarehousing> wrapper = new QueryWrapper<>();
            wrapper.lambda().ne(DrugsWarehousing::getStatus, PresConstants.PresDrugsStatus.DEL)
                    .eq(DrugsWarehousing::getPharId, loginInfo.getPharId())
                    .eq(DrugsWarehousing::getReceiptNo, model.getReceiptNo());
            DrugsWarehousing one = getOne(wrapper);
            if (one != null) {
                failModel.add(model.getHerbName());
                continue;
            }
            QueryWrapper<DrugsModel> qs = new QueryWrapper<>();
            qs.lambda().eq(DrugsModel::getDrugnum, model.getDrugnum())
                    .eq(DrugsModel::getPharId, loginInfo.getPharId())
                    .ne(DrugsModel::getStatus, PresConstants.ModelDrugsStatus.DEL);
            DrugsModel modelOne = drugsModelService.getOne(qs);
            if (modelOne == null) {
                failModel.add(model.getHerbName());
                continue;
            }
            if (!modelOne.getHerbName().equals(model.getHerbName())) {
                failModel.add(model.getHerbName());
                continue;
            }
            one = new DrugsWarehousing();
            BeanUtils.copyProperties(model, one);
            one.setCreateDate(LocalDateTime.now());
            one.setStatus(DrugsConstants.WareStatus.NOMAL);
            one.setOperId(loginInfo.getId());
            one.setPharId(loginInfo.getPharId());
            one.setUseUnit(modelOne.getUseUnit())
                    .setPrice(modelOne.getPrice())
                    .setCostPrice(modelOne.getOriginalPrice())
                    .setSpecification(modelOne.getSpecification());
            if (model.getTermDate() != null) {
                one.setTermDate(model.getTermDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
            }
            boolean save = save(one);
            if (!save) {
                failModel.add(one.getHerbName());
                continue;
            }
            if (modelOne.getQty() == null) {
                modelOne.setQty(new BigDecimal(0));
            }
            if (one.getWareQty() != null) {
                modelOne.setQty(modelOne.getQty().add(one.getWareQty()));
            }
            save = drugsModelService.updateById(modelOne);
            if (!save) {
                continue;
            }
        }
        Map<String, String> result = new HashMap<>();
        result.put("success", list.size() - failModel.size() + "");
        result.put("fail", failModel.size() + "");
        String failMsg = "";
        if (CollectionUtil.isNotEmpty(failModel)) {
            failMsg = StringUtils.join(failModel, ",");
        }
        result.put("failMsg", failMsg);
        return result;
    }

    /**
     * @param req:
     * @return Page<DrugsWarePageRes>
     * @description 分页查询入库记录
     * @author czg
     * @date 2023/4/19 14:21
     */
    @Override
    public Page<DrugsWarePageRes> getDrugsWarePage(DrugsWarePageReq req) {
        Page<DrugsWarePageRes> page = req.pagePojo();
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        if (loginInfo.getType() == LoginInfo.UserType.PHAR) {
            req.setPharId(loginInfo.getPharId());
        }
        page = getBaseMapper().getDrugsWarePage(page, req);
        return page;
    }

    /**
     * @param req:
     * @return Page<DrugsQtyPageRes>
     * @description 查询药品库存列表
     * @author czg
     * @date 2023/4/19 20:40
     */
    @Override
    public Page<DrugsQtyPageRes> getDrugsQtyPage(DrugsQtyPageReq req) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        if (loginInfo.getType() == LoginInfo.UserType.PHAR) {
            req.setPharId(loginInfo.getPharId());
        }
        Page<DrugsQtyPageRes> page = req.pagePojo();
        page = getBaseMapper().getDrugsQtyPage(page, req);

        return page;
    }

    @Override
    public List<DrugsQtyRes> getDrugsIsHaveQty(String drugnums, Integer pharId) {
        if (StringUtils.isBlank(drugnums)) {
            throw new ZekeException(400, "药品编码不能为空");
        }
        String[] drugNums = drugnums.split(",");
        Integer pharFlag = pharmacyService.getPharmacyFlag(pharId);
        List<DrugsQtyRes> drugsQtyRes = this.baseMapper.getDrugsIsHaveQty(drugNums, pharFlag);
        if (CollectionUtil.isNotEmpty(drugsQtyRes)) {
            for (DrugsQtyRes res : drugsQtyRes) {
                Integer qyt = res.getQty() == null ? 0 : res.getQty().intValue();
                if (qyt > 0) {
                    res.setIsQty(true);
                } else {
                    res.setIsQty(false);
                }
            }
        }
        return drugsQtyRes;
    }
}
